﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class AnimalBase
{
public:
	//void speak()
	virtual void speak()
	{
		cout << "动物在说话！" << endl;
	}
	virtual void eat()
	{
		cout << "动物在吃饭！" << endl;
	}
};
class Cat :public AnimalBase
{
public:
	//void speak()
	virtual void speak()
	{
		cout << "小猫在说话！" << endl;
	}
	virtual void eat()
	{
		cout << "小猫在吃鱼！" << endl;
	}
};
//2.调用doSpeak，speak()函数的地址早就绑定好了，是早绑定；此时，为静态编译，编译阶段就确定好了地址；
	//如果想调用Cat的speak()，就不能提前绑定好函数的地址了，所以需要在运行的时候再去确定函数地址；即动态联编，
	//写法是，将doSpeak方法改为虚函数，在父类AnimalBase上声明虚函数，发生了多态；
//3.多态，父类的引用或指针，指向子类对象；AnimalBase& animal = cat;
void doSpeak(AnimalBase& animal)
{
	animal.speak();
}
//1.如果发生了继承的关系，编译器允许进行类型转换；
void testAnimalSpeak()
{
	Cat cat;
	doSpeak(cat);//动物在说话！ --> 小猫在说话！

	cout << sizeof(AnimalBase) << endl;//1 --> 4

	//4.父类指针指向子类对象，多态；
	AnimalBase* animal = new Cat;
	animal->speak();//小猫在说话！

	//5.animal是地址，强转成int*类型指针地址，*取地址指向值；*(int*)animal，找到虚函数表；
		//*(int*)*(int*)animal，函数地址；
	((void(*)()) * (int*)*(int*)animal)();//小猫在说话！
	//6.猫吃鱼的地址，*((int*)*(int*)animal+1)；
	((void(*)()) * ((int*)*(int*)animal + 1))();//小猫在吃鱼！
}

//main293：静态联编和动态联编
int main293()
{
	testAnimalSpeak();

	system("pause");
	return EXIT_SUCCESS;
}